#include <iostream>
#include "Comenzador.h"
#include "BuscadorArchivos.h"
#include "Constantes.h"
#include <math.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/param.h>
#include <stdio.h>
#include "string.h"
#include "ArbolTrie.h"
#include "Analizador_Sintactico.h"
using namespace std;

int main(int argc, char** argv) {
	unsigned int tam_dir = 0;
	bool reindexar = false, vacio = true;
	std::fstream documentos(nom_arch_doc);
	std::fstream directorios(nom_arch_dir);
	std::fstream terminos(nom_arch_terminos);
	std::fstream dir_escritura(nom_arch_dir_aux, ios::trunc | ios::in | ios::out);
	std::string opcion, terminos_a_buscar;
	Analizador_Sintactico analizador;
	char op;

	std::string dir_a_indexar;
	std::string linea, linea_ant;


	if(!documentos.is_open())
		documentos.open(nom_arch_doc, ios::trunc | ios::in | ios::out);
	if(!directorios.is_open())
		directorios.open(nom_arch_dir, ios::trunc | ios::in | ios::out);
	if(!terminos.is_open())
		terminos.open(nom_arch_terminos, ios::trunc | ios::in | ios::out);

	Comenzador comen;
	BuscadorArchivos *busca = new BuscadorArchivos(&documentos, &directorios, &dir_escritura, &analizador);
	// Busca los últimos numeros de Documentos y Directorios
	busca->getUltimoDocDir();
	ArbolTrie *arbol = NULL;
	arbol = new ArbolTrie();
	vacio = !comen.cargarTerminos(&terminos, arbol);
	/*
	 * Buscar si el dir_a_indexar esta en directorios.txt
	 * Si está => indexar todo de vuelta, por ende leer secuencialmente el directorios.txt y mandarlo al buscador, y borrar el documentos.txt
	 * Sino agregar ese solo
	 */
	while((opcion = comen.continuar_aplicacion()).compare("-s") != 0) {
		// e de error
		op = 'e';
		if(opcion.size() > 4) {
			if(opcion.at(0) == '-') {
				op = opcion.at(1);
				// Si en la posición 2 no hay un espacio, se pasaron mal los argumentos
				if(opcion.at(2) != ' ')
					op = 'e';
				else {
					// Si en la posición 3 hay un / esto quiere decir q continua con un directorio
					if(opcion.at(3) == '/')
						dir_a_indexar = opcion.substr(3, opcion.size() - 3);
					if(opcion.at(opcion.size() - 1) == '/')
						dir_a_indexar = dir_a_indexar = opcion.substr(3, opcion.size() - 4);
					if((opcion.at(3) != '/') && (op == 'q'))
						terminos_a_buscar = opcion.substr(3, opcion.size() - 3);
				}
			}
		}
		else {
			if(opcion.size() == 2)
				if((op = opcion.at(1)) == 'b') { // si ingresas -b borra todo
					comen.borrarTodo(&documentos);
					terminos.close();
					directorios.close();
					documentos.close();
					dir_escritura.close();
					busca->vaciarDatos_Arch();
					terminos.open(nom_arch_terminos, ios::trunc | ios::in | ios::out);
					directorios.open(nom_arch_dir, ios::trunc | ios::in | ios::out);
					documentos.open(nom_arch_doc, ios::trunc | ios::in | ios::out);
					dir_escritura.open(nom_arch_dir_aux, ios::trunc | ios::in | ios::out);
					busca->resetearNum();
					delete arbol;
					arbol = new ArbolTrie();
					std::cout << "Indexador reiniciado" << std::endl;
					vacio = true;
				}
		}
		//cout << "dir_a_indexar " << dir_a_indexar << endl;
		//getchar();
		// op = i ("i" de indexar) => indexo el directorio
		if(op == 'i') {
			if(comen.existe_dir(dir_a_indexar, &directorios)) {
				reindexar = true;
				//cout << "ENTRO 1" << endl;
				// Al reindexar, el árbol empieza de 0
				delete arbol;
				arbol = new ArbolTrie();
				//cout << "ENTRO 1" << endl;
				// documentos.clear();
				//getchar();
				documentos.close();
				documentos.open(nom_arch_doc, ios_base::in| ios_base::out| std::ios_base::trunc);
				busca->resetearNum();
				busca->vaciarDatos_Arch();

				while(getline(directorios, linea)) {
					linea.erase(linea.size() - 2, 2);
					cout << linea << endl;
					if((linea_ant.size() < linea.size()) && (linea.find_first_of(linea_ant) == 0)) {
						if(linea.at(linea_ant.size()) != '/') {
							linea_ant = linea;
							busca->buscador(linea.c_str());
						}
					}
					else {
						linea_ant = linea;
						busca->buscador(linea.c_str());
					}
				}
			}
			else {
				/*
				 *  Se agrega ese solo, o se reindexa los directorios ya indexados excepto aquellos que
				 *  se encuentren contenidos por el directorio a indexar más el dir a agregar
				 */
				if(comen.existe_subdir(dir_a_indexar, &directorios)) {
					reindexar = true;
					//cout << "ENTRO 2" << endl;
					// Al reindexar, el árbol empieza de 0
					delete arbol;
					arbol = new ArbolTrie();
					//cout << "ENTRO 2" << endl;
					//getchar();
					documentos.close();
					documentos.open(nom_arch_doc, ios_base::in|ios_base::out |std::ios::trunc);
					busca->resetearNum();
					//busca = new BuscadorArchivos(&documentos, &directorios, &dir_escritura, reindexar);
					busca->vaciarDatos_Arch();
					while(getline(directorios, linea)) {
						linea.erase(linea.size() - 2, 2);
						if((dir_a_indexar.size() < linea.size()) && (linea.find_first_of(dir_a_indexar) == 0)) {
							/*
							 *  Si lo que leo es un subdirectorio de dir_a_idx (if con '/') entonces no hago nada,
							 *  si no, me fijo si es un subdirectorio de un directorio ya indexado
							 */
							if(linea.at(dir_a_indexar.size()) != '/') {
								//linea_ant = linea;
								//busca->buscador(linea.c_str());
								if((linea_ant.size() < linea.size()) && (linea.find_first_of(linea_ant) == 0)) {
									if(linea.at(linea_ant.size()) != '/') {
										linea_ant = linea;
										busca->buscador(linea.c_str());
									}
								}
								else {
									linea_ant = linea;
									busca->buscador(linea.c_str());
								}
							}
						}
						else {
							linea_ant = linea;
							busca->buscador(linea.c_str());
						}
					}
					busca->buscador(dir_a_indexar.c_str());
				}
				else {
					reindexar = false;
					//cout << "ENTRO 3" << endl;
					//busca = new BuscadorArchivos(&documentos, &directorios, &dir_escritura, reindexar);
					documentos.seekg(0, std::ios_base::end);
					busca->buscador(dir_a_indexar.c_str());
				}
			}

			directorios.seekg(0, std::ios_base::end);
			tam_dir = directorios.tellg();

			if((tam_dir == 0) || (reindexar)) {
				directorios.close();
				dir_escritura.close();
				comen.mover_archivos(nom_arch_dir, nom_arch_dir_aux);
				directorios.open(nom_arch_dir, ios::in | ios::out);
				dir_escritura.open(nom_arch_dir_aux, ios::trunc | ios::in | ios::out);
			}

			if((!reindexar) && (tam_dir > 0)) {
				comen.unir_archivos(&directorios, &dir_escritura, nom_arch_dir_aux);
				dir_escritura.open(nom_arch_dir_aux, ios::trunc | ios::in | ios::out);
			}

			// Ordena los archivos de términos alfabeticamente, agrupa los q son iguales y los indexa
			comen.ordenar_archivos(&documentos, arbol);
			vacio = false;
		}
		if((op == 'q') && (!vacio)) {
			std::cout << "Consulsta de : " << terminos_a_buscar << std::endl;
			comen.consulta(terminos_a_buscar, arbol, busca->getNum_Doc(), busca->getDatosArch(), &documentos);
			terminos_a_buscar.clear();
		}
		if((op == 'q') && (vacio)) {
			std::cout << "No hay ningún archivo indexado, nose puede buscar nada" << std::endl;
		}
	}

	// Recorriendo el árbol, escribo todo sus terminos en un archivo
	arbol->recorrerArbol(&terminos);

	// Elimino los archivos auxiliares creados
	comen.eliminar_arch_auxiliares(&documentos);

	// Libero la memoria usada para el árbol
	delete arbol;

	// delete comen;
	if(busca != NULL)
		delete busca;
	cout << "Fin de la aplicación" << endl;
	return 0;
}
